package com.xwj.juc;

import java.util.concurrent.*;

/**
 * CountDownLatchDemo
 * 线程等待直到计数器减为0时开始工作
 * 构造器中的计数值（count）实际上就是闭锁需要等待的线程数量，这个值只能被设置一次，而且CountDownLatch没有提供任何机制去重新设置这个计数值
 *
 * @author xwj
 * @date 2021/2/2
 */
public class CountDownLatchDemo {
    ExecutorService executorService = Executors.newFixedThreadPool(20);

    public static void main(String[] args) {
        CountDownLatchDemo count = new CountDownLatchDemo();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                final int temp = 1;
                count.search(temp);
            }, "查询线程").start();
        }
    }

    public void search(Integer key) {
        final CountDownLatch countDownLatch = new CountDownLatch(4);
        System.out.println(countDownLatch.getCount());
        // 新建线程方式，每次执行都需要创建新线程，浪费资源
//        FutureTask<Object> futureTask1 = new FutureTask<>(new SearchTask1(countDownLatch));
//        new Thread(futureTask1).start();
//        FutureTask<Object> futureTask2 = new FutureTask<>(new SearchTask2(countDownLatch));
//        new Thread(futureTask2).start();
//        FutureTask<Object> futureTask3 = new FutureTask<>(new SearchTask3(countDownLatch));
//        new Thread(futureTask3).start();
//        FutureTask<Object> futureTask4 = new FutureTask<>(new SearchTask4(countDownLatch));
//        new Thread(futureTask4).start();
//        try {
//            System.out.println(futureTask1.get());
//            System.out.println(futureTask2.get());
//            System.out.println(futureTask3.get());
//            System.out.println(futureTask4.get());
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        } catch (ExecutionException e) {
//            e.printStackTrace();
//        }
        // 使用线程池，线程复用，便于管理，减少线程创建引起的资源浪费
        FutureTask<Object> futureTask1Result = (FutureTask<Object>) executorService.submit(new SearchTask1(countDownLatch));
        FutureTask<Object> futureTask2Result = (FutureTask<Object>) executorService.submit(new SearchTask2(countDownLatch));
        FutureTask<Object> futureTask3Result = (FutureTask<Object>) executorService.submit(new SearchTask3(countDownLatch));
        FutureTask<Object> futureTask4Result = (FutureTask<Object>) executorService.submit(new SearchTask4(countDownLatch));
        try {
            countDownLatch.await();
            System.out.println("等待4个查询任务完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            System.out.println(futureTask1Result.get());
            System.out.println(futureTask2Result.get());
            System.out.println(futureTask3Result.get());
            System.out.println(futureTask4Result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 任务1
 */
class SearchTask1 implements Callable<Object> {
    private final CountDownLatch countDownLatch;

    public SearchTask1(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "开始执行");
        TimeUnit.MILLISECONDS.sleep(1000);
        countDownLatch.countDown();
        return Thread.currentThread().getName() + "SearchTask1完成";
    }
}

/**
 * 任务2
 */
class SearchTask2 implements Callable<Object> {
    private final CountDownLatch countDownLatch;

    public SearchTask2(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "开始执行");
        TimeUnit.MILLISECONDS.sleep(500);
        countDownLatch.countDown();
        return Thread.currentThread().getName() + "SearchTask2完成";
    }
}

/**
 * 任务3
 */
class SearchTask3 implements Callable<Object> {
    private final CountDownLatch countDownLatch;

    public SearchTask3(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "开始执行");
        TimeUnit.MILLISECONDS.sleep(200);
        countDownLatch.countDown();
        return Thread.currentThread().getName() + "SearchTask3完成";
    }
}

/**
 * 任务4
 */
class SearchTask4 implements Callable<Object> {
    private final CountDownLatch countDownLatch;

    public SearchTask4(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getName() + "开始执行");
        TimeUnit.MILLISECONDS.sleep(1200);
        countDownLatch.countDown();
        return Thread.currentThread().getName() + "SearchTask4完成";
    }
}
